package com.motu.vertx.module.utility.webtool;


import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Iterator;
import java.util.Map;

import static java.nio.charset.StandardCharsets.UTF_8;

public class EncryptTool {

	/**
	 * <p>@title aesGcmEncrypt</p>
	 * <p>@description Aes-Gcm加密</p>
	 *
	 * @param content 待加密文本
	 * @param key     密钥
	 * @return java.lang.String
	 */
	public static String aesGcmEncrypt(String content, byte[] key) {
		try {
			// 根据指定算法ALGORITHM自成密码器
			Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
			SecretKeySpec skey = new SecretKeySpec(key, "AES");
			cipher.init(Cipher.ENCRYPT_MODE, skey);
			//获取向量
			byte[] ivb = cipher.getIV();
			byte[] encodedByteArray = cipher.doFinal(content.getBytes(UTF_8));
			byte[] message = new byte[ivb.length + encodedByteArray.length];
			System.arraycopy(ivb, 0, message, 0, ivb.length);
			System.arraycopy(encodedByteArray, 0, message, ivb.length, encodedByteArray.length);
			return Base64.getEncoder().encodeToString(message);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
				| BadPaddingException e) {
			//建议自行调整为日志输出或抛出异常
			return null;
		}
	}

	/**
	 * <p>@title aesGcmDecrypt</p>
	 * <p>@description Aes-Gcm解密</p>
	 *
	 * @param content 带解密文本
	 * @param key     密钥
	 * @return java.lang.String
	 */
	public static String aesGcmDecrypt(String content, byte[] key) {
		try {
			// 根据指定算法ALGORITHM自成密码器
			Cipher decryptCipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
			SecretKeySpec skey = new SecretKeySpec(key, "AES");
			byte[] encodedArrayWithIv = Base64.getDecoder().decode(content);
			GCMParameterSpec decryptSpec = new GCMParameterSpec(128, encodedArrayWithIv, 0, 12);
			decryptCipher.init(Cipher.DECRYPT_MODE, skey, decryptSpec);
			byte[] b = decryptCipher.doFinal(encodedArrayWithIv, 12, encodedArrayWithIv.length - 12);
			return new String(b, UTF_8);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
				| BadPaddingException | InvalidAlgorithmParameterException e) {
			//建议自行调整为日志输出或抛出异常
			return null;
		}
	}

	/**
	 * <p>@title sign</p>
	 * <p>@description 签名</p>
	 *	SHA-256算法
	 * @param toBeSignStr 待签名字符串
	 * @return java.lang.String
	 */
	public static String SHA256(String toBeSignStr) throws NoSuchAlgorithmException {
		MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
		messageDigest.update(toBeSignStr.getBytes(UTF_8));
		return byteToHexString(messageDigest.digest());
	}

	/***
	 * @version 1.0 通过SHA256算法得到数据签名
	 * @return 返回base64编码
	 **/
	public static String getSign (String secretKey,JsonObject params,String encryptBody) throws NoSuchAlgorithmException {
	/*	1.文档要求
		将除去 sign 的系统参数和除去请求体外的业务参数，根据参数的 key 进行 字典排序，并按照 Key-Value 的格式拼接成一个字符串。
		将请求体中的参数 拼接在字符串最后。
		2.secretKey 拼接在步骤 1 获得字符串最前面，得到待加密字符串*/
		String msg = secretKey;
		for (Iterator<Map.Entry<String, Object>> iter1 = params.iterator(); iter1.hasNext();) {
			Map.Entry<String, Object> entry1 = iter1.next();
			String key = entry1.getKey();
			String val = (String) entry1.getValue();
			msg += key + val;
		}
		msg += encryptBody;
		return EncryptTool.SHA256(msg);
	}

	/**
	 * <p>@title byteToHexString</p>
	 * <p>@description byte数组转化为16进制字符串</p>
	 *
	 * @param bytes byte数组
	 * @return java.lang.String
	 */
	public static String byteToHexString(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte aByte : bytes) {
			String strHex = Integer.toHexString(aByte);
			if (strHex.length() > 3) {
				sb.append(strHex.substring(6));
			} else {
				if (strHex.length() < 2) {
					sb.append("0").append(strHex);
				} else {
					sb.append(strHex);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * <p>@title hexStringToByte</p>
	 * <p>@description 十六进制string转二进制byte[]</p>
	 *
	 * @param str 十六进制字符串
	 * @return byte[]
	 */
	public static byte[] hexStringToByte(String str) {
		byte[] baKeyword = new byte[str.length() / 2];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				baKeyword[i] = (byte) (0xff & Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16));
			} catch (Exception e) {
				//建议自行调整为日志输出或抛出异常
				e.printStackTrace();
			}
		}
		return baKeyword;
	}

	public static Future<JsonObject> verifyFromApi(String ai, String cardNo, String realName, WebClient webClient)throws NoSuchAlgorithmException {
		Promise<JsonObject> promise = Promise.promise();
		//应用标识 (APPID)
		String appId = "b0b61960cd7d404289a52a2b2af28edd";
		//应用密钥 (Secret Key)
		String secretKey = "fc83693be7300faba7b1e6626c8c1b29";
		//bizId 业务权限标识(gameId)
		String bizId = "1101999999";

		// 处理密钥（将16进制字符串密钥转换为byte数组）
		byte[] keyBytes = EncryptTool.hexStringToByte(secretKey);

		//当前时间戳 精确到毫秒
		String timestamps = String.valueOf(System.currentTimeMillis());

		//上下线
//        List<JsonObject> list = new ArrayList<>();
//        JsonObject tmp = new JsonObject();
//        tmp.put("no",1);
//        tmp.put("si","qwertgyhujikolmj87hgbvftgusuijuy");
//        tmp.put("bt",1);
//        tmp.put("ot",timestamps);
//        tmp.put("ct",0);
//        tmp.put("pi","1fffbkmd9ebtwi7u7f4oswm9li6twjydqs7qjv");
//        list.add(tmp);
//        msg.put("collections",list);
		JsonObject msg = new JsonObject();
		//待加密数据
		String testMsg = "{\"ai\":\"" + ai + "\",\"name\":\"" + realName + "\",\"idNum\":\"" + cardNo + "\"}";

		//加密后请求体数据
		String encryptBody = EncryptTool.aesGcmEncrypt(testMsg,keyBytes);


		JsonObject data = new JsonObject();
		data.put("data",encryptBody);
		encryptBody = data.toString();

//		String sign = getSign(secretKey,appId,bizId,timestamps,encryptBody);
//
//		String url = "https://wlc.nppa.gov.cn/test/collection/loginout/QHKqNn";
//		webClient
////                .getAbs(url)
//				.postAbs(url)
//				.putHeader("Content-Type", "application/json; charset=utf-8")
//				.putHeader("appId", appId)
//				.putHeader("bizId", bizId)
//				.putHeader("timestamps", timestamps)
//				.putHeader("sign", sign)
//				.sendJsonObject(data, handle -> {
//					if (handle.succeeded()) {
//						JsonObject result = handle.result().body().toJsonObject();
//						System.out.println("result:------------------");
//						System.out.println(result);
//						System.out.println("result:------------------");
//						promise.complete(result);
//					}
//				});
		return promise.future();
	}
}
